package geom;

import geom.Geom;
import geom.Line;
import geom.Vector;

import java.util.ArrayList;
import java.util.Iterator;

import processing.core.PApplet;


public class AngleField implements Field{
	ArrayList<Line> lines;
	boolean buffered = false;
	ArrayList<ArrayList<Vector>> buffer;
	
	public AngleField(){
		lines = new ArrayList<Line>();
	}
	public AngleField(ArrayList<Line> lines){
		this.lines = new ArrayList<Line>();
		this.lines.addAll(lines);
	}
	
	public void buffer(int x, int y, int step){
		int sx = Math.round(x / step);
		int sy = Math.round(y / step);
		buffered = false;
		buffer = new ArrayList<ArrayList<Vector>>(sx); 
		for(int ix = 0; ix < sx; ix++){
			ArrayList<Vector> bi = new ArrayList<Vector>(sy);
			for(int iy = 0; iy < sy; iy++){
				bi.add(value(new Vector(sx*step, sy*step)));
			}	
			buffer.add(bi);
		}
		buffered = true;
	}
	
	public void getBuffered(Vector v){
		Iterator<ArrayList<Vector>> i1 = buffer.iterator();
		while(i1.hasNext()){
			//Iterator.
		}
	}
	
	public void add(ArrayList<Line> line){
		lines.addAll(line);
	}
	
	public ArrayList<Line> preselect(Vector v, int dist){
		ArrayList<Line> pre = new ArrayList<Line>();
		Iterator<Line> il = lines.iterator();
		while(il.hasNext()){
			Line next = il.next();
			if(next.v1.manhattanDistance(v) < dist ||
			   next.v2.manhattanDistance(v) < dist){
				pre.add(next);
			}
		}
		return pre;
	}
	
	public Vector value(Vector v) {
		Vector val = new Vector();
		ArrayList<Line> pre = preselect(v, 250);
		Iterator<Line> il = lines.iterator();
		while(il.hasNext()){
			Line next = il.next();
			if(v == null) System.out.println("v == null");
			float dist = Geom.getDistanceFromPointToLineXY(next.v1, next.v2, v);
			float scaled = sigE(dist, 8f);
			val = val.add(next.relative().mult(scaled));
		}
		//val.x = 1f-sigE(val.x, 5);
		//val.y = 1f-sigE(val.y, 5);
		return val;
	}
	
	public void draw(PApplet pa, float w, float h, float step){
		int wsteps = Math.round(w / step);
		int hsteps = Math.round(h / step);
		for(int x = 0; x < wsteps; x++){
			for(int y = 0; y < hsteps; y++){
				Vector pos = new Vector(x*step, y*step);
				Vector end = value(pos).mult(3).add(pos);
				pa.line(pos.x, pos.y, end.x, end.y);
			}
		}
	}
	
	public float sigmoid(float v){
		return 1f / (1f + (float)Math.pow(Math.E, v));
	}
	
	public float sigE(float v, float div){
		return 1f / (float)Math.pow(Math.E, v/div);
	}

}
